/*
 * main.c
 *
 *  Created on: 17.11.2009
 *      Author: Anton Golubkov
 */

// Using sample of using sd card reader


/*
 * Copyright (c) 2006-2009 by Roland Riegel <feedback@roland-riegel.de>
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <string.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#include <util/delay.h>
#include "sd_fat/fat.h"
#include "sd_fat/fat_config.h"
#include "sd_fat/partition.h"
#include "sd_fat/sd_raw.h"
#include "sd_fat/sd_raw_config.h"
#include "sd_fat/uart.h"
#include "blink.h"

static uint8_t find_file_in_dir(struct fat_fs_struct* fs,
		struct fat_dir_struct* dd, const char* name,
		struct fat_dir_entry_struct* dir_entry);

static struct fat_file_struct* open_file_in_dir(struct fat_fs_struct* fs,
		struct fat_dir_struct* dd, const char* name);

static uint8_t fat_touch(struct fat_dir_struct* dd, const char* filename);

static uint8_t fat_write(struct fat_fs_struct* fs, struct fat_dir_struct* dd,
		const char* filename, int32_t offset, const char *buffer,
		uint8_t sizeofbuffer);

unsigned char currentChannel = 0;
uint16_t newSample;
unsigned char newSampleReady = 0;

/* Interrupt service routines */
ISR(ADC_vect)
{
//	blink(2, 50);
	newSample = ADC;
	newSampleReady = 1;
/*	if (currentChannel < 4) {//Cycle trough the channels 0-4
		currentChannel++;
	} else {
		newSampleReady = 1;
		currentChannel = 0;
	}*/
	//ADMUX = currentChannel;//Update the ADMUX register
	//ADMUX |= (1 << MUX2);
}

/* Sub-rutine */
void process_Data(void) {
	newSampleReady = 0;

} //Does in fact nothing...

void adc_init() {
	ADCSRA = 0;
	ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Set ADC prescaler to 128 - 125KHz sample rate @ 16MHz

	ADCSRA |= (1 << ADATE); // Set ADC to Free-Running Mode

	ADMUX |= 0; //(1 << MUX2); // ADC channel 0


	ADCSRA |= (1 << ADEN); //Enable the ADC
	ADCSRA |= (1 << ADIE); // Enable ADC Interrupt
	sei();
	// Enable Global Interrupts
	ADCSRA |= (1 << ADSC); //Start first conversion in Free-running mode
	//Now the conversions are running
	//Channels are changed in interrupt service routine
}

static char data[5];

int main() {
	/* we will just use ordinary idle mode */
	//	set_sleep_mode(SLEEP_MODE_IDLE);


	struct partition_struct* partition;
	struct fat_fs_struct* fs;
	struct fat_dir_entry_struct directory;
	struct fat_dir_struct* dd;
	ioinit();

	blink(3, 200);

	while (1) {
		blink(2, 100);
		/* setup sd card slot */
		if (!sd_raw_init()) {
			continue;
		}

		/* open first partition */
		partition = partition_open(sd_raw_read,
				sd_raw_read_interval, sd_raw_write, sd_raw_write_interval, 0);

		if (!partition) {
			/* If the partition did not open, assume the storage device
			 * is a "superfloppy", i.e. has no MBR.
			 */
			partition = partition_open(sd_raw_read, sd_raw_read_interval,
					sd_raw_write, sd_raw_write_interval, -1);
			if (!partition) {
				//opening partition failed
				continue;
			}
		}

		/* open file system */
		fs = fat_open(partition);
		if (!fs) {
			// opening filesystem failed
			continue;
		}

		/* open root directory */
		fat_get_dir_entry_of_path(fs, "/", &directory);

		dd = fat_open_dir(fs, &directory);
		if (!dd) {
			continue;
		}

		blink(5, 100);
		break;
	}

	char filename[13];
	strcpy(filename, "TEST000.TXT");
	fat_touch(dd, filename);
	int32_t offset = 0;
	int16_t byte_to_write = 255;

	adc_init();

	int i;
	i  = 0;
	while (i < 1000) {
		_delay_ms(20);
		if (newSampleReady) { //If new sample available
			newSampleReady = 0;
			data[0] = (newSample >> 8);
			data[1] = (newSample & 0x00FF);
			data[2] = '\n';
			fat_write(fs, dd, filename, offset, data, 3);
			offset += 3;
			blink(1, 5);
			i++;
		}

	}
	ADCSRA &= ~(1 << ADEN); //Disable the ADC
	sd_raw_sync();

	/* close file system */
	fat_close(fs);

	/* close partition */
	partition_close(partition);
	blink(5, 1000);
	return 0;
}

uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd,
		const char* name, struct fat_dir_entry_struct* dir_entry) {
	while (fat_read_dir(dd, dir_entry)) {
		if (strcmp(dir_entry->long_name, name) == 0) {
			fat_reset_dir(dd);
			return 1;
		}
	}

	return 0;
}

struct fat_file_struct* open_file_in_dir(struct fat_fs_struct* fs,
		struct fat_dir_struct* dd, const char* name) {
	struct fat_dir_entry_struct file_entry;
	if (!find_file_in_dir(fs, dd, name, &file_entry))
		return 0;

	return fat_open_file(fs, &file_entry);
}

static uint8_t fat_touch(struct fat_dir_struct* dd, const char* filename) {
	struct fat_dir_entry_struct file_entry;
	return fat_create_file(dd, filename, &file_entry);

}

static uint8_t fat_write(struct fat_fs_struct* fs, struct fat_dir_struct* dd,
		const char* filename, int32_t offset, const char *buffer,
		uint8_t sizeofbuffer) {

	/* search file in current directory and open it */
	struct fat_file_struct* fd = open_file_in_dir(fs, dd, filename);
	if (!fd) {
		// Error open file
		blink(10, 500);
		return 0;
	}

	if (!fat_seek_file(fd, &offset, FAT_SEEK_SET)) {
		blink(10, 500);
		return 0;
	}
	/* write buffer to file */
	if (fat_write_file(fd, (uint8_t*) buffer, sizeofbuffer) != sizeofbuffer) {
		blink(10, 500);
		// error writing to file
		return 0;
	}
	fat_close_file(fd);
	return 1;
}

